#include "config.h"
#include "bulverde.h"
#include "time.h"
#include "irq.h"

/* jiffies should be defined as volatile */
volatile unsigned long jiffies=0;
volatile unsigned long jiffies_div10=0;

void TimerInit(void)
{
	u32 old_rcnr = __REG(RTC_BASE_PHYSICAL+RCNR_OFFSET);

	/* enable 32-kHz oscillator on */
	__REG(CLK_BASE_PHYSICAL+OSCC_OFFSET) = OSCC_OON;

	/* disable timer interrupts and clear the AL and HZ bits*/
	__REG(RTC_BASE_PHYSICAL+RTSR_OFFSET) = (RTSR_AL | RTSR_HZ);

	/* put the counter to 0 */
	/* strange enough, this doesn't seem to work -- Erik */
	/* RCNR = 0x0; */

	/* RCNR writes may be delayed by a 32-kHz clock cycle */
	__REG(RTC_BASE_PHYSICAL+RCNR_OFFSET) = 0x0;

	while (__REG(RTC_BASE_PHYSICAL+RCNR_OFFSET) > old_rcnr);

	/* os timer */
	cli();
	__REG(OST_BASE_PHYSICAL+OSCR0_OFFSET) = 0;
	__REG(OST_BASE_PHYSICAL+OSMR0_OFFSET) = (3250000L)/TIMER_TICK_PER_SEC ; /* Trigger interrupts every 10 ms */
	__REG(OST_BASE_PHYSICAL+OSSR_OFFSET) = 0xFFF;
	__REG(OST_BASE_PHYSICAL+OIER_OFFSET) = OIER_E0;

#if 0	/* Nam9, 2004. 9. 5 */
	/* milli-second timer */
	__REG(OST_BASE_PHYSICAL+OSCR4_OFFSET) = 0;
	/* __REG(OST_BASE_PHYSICAL+OMCR4_OFFSET) = 0xC9;	/\* Increase every 1/1000000 sec *\/ */
	__REG(OST_BASE_PHYSICAL+OMCR4_OFFSET) = 0xCC;	/* Increase every 1/1000000 sec */
	__REG(OST_BASE_PHYSICAL+OSMR4_OFFSET) = 1000; /* Trigger interrupts every 1 ms */
	__REG(OST_BASE_PHYSICAL+OSSR_OFFSET) = 0xFFF;
	__REG(OST_BASE_PHYSICAL+OIER_OFFSET) = (OIER_E0 | OIER_E4) & 0xFFF;


	/* Interrupt Initailization routine */
	__REG(INTC_BASE_PHYSICAL+ICCR_OFFSET) = 1;	/* Only active,unmasked irq. bring processor out of idle mode */
	__REG(INTC_BASE_PHYSICAL+ICLR_OFFSET) = 0;
	__REG(INTC_BASE_PHYSICAL+ICMR_OFFSET) = IRQ_OST0 | IRQ_OST_4_11;
	__REG(INTC_BASE_PHYSICAL+ICMR2_OFFSET) = 0;
#else
	/* Interrupt Initailization routine */
	__REG(INTC_BASE_PHYSICAL+ICCR_OFFSET) = 0;
	__REG(INTC_BASE_PHYSICAL+ICLR_OFFSET) = 0;
	__REG(INTC_BASE_PHYSICAL+ICMR_OFFSET) = IRQ_OST0;
	__REG(INTC_BASE_PHYSICAL+ICMR2_OFFSET) = 0;
#endif
//	sti();

}

/* returns the time in seconds */
u32  TimerGetTime(void)
{
	return ( (u32) __REG(RTC_BASE_PHYSICAL+RCNR_OFFSET));
}

/* returns the time in 1/100seconds */
u32  TimerGetCentiTime(void)
{
	return((u32) jiffies/(TIMER_TICK_PER_SEC*100));
}

void ostdelay(int uSec);

void msleep_cli(unsigned int ms)
{
	unsigned long init_jiffies;

	init_jiffies = __REG(OST_BASE_PHYSICAL+OSCR0_OFFSET);

	while( (init_jiffies + (unsigned long)(ms / 10) ) > __REG(OST_BASE_PHYSICAL+OSCR0_OFFSET) ) {;}

}

void ostdelay(int uSec)
{
    unsigned long time = OSCR;
    unsigned long expireTime = time + (uSec * 3);   // approx 3 ticks per uS;

    //
    // Check if we wrapped on the expireTime
    // and delay first part until wrap
    //
    if (expireTime < time)
    {
        while (time < OSCR) {
        }
    }

    while (OSCR <= expireTime){
    }

    return ;
}
